home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 6
/
FM Towns Free Software Collection 6.iso
/
t_os
/
chtiff
/
source
/
chtiff1.c
next >
Wrap
Text File
|
1993-07-08
|
11KB
|
435 lines
/*
TownsTIFF ←→ NeXTTIFF コンバーター
ファイル読み込み部分
*/
#include<stdio.h>
#include<stdlib.h>
#include"define.h"
#define READ_SECTION 1
#include"function.h"
/*
offset=0なら、現在のファイルポインタから読む。
ちなみにここは、モトローラ・Intel形式を吸収する役目もあります。
*/
unsigned char read_BYTE(unsigned long offset)
{
unsigned long backup_offset;
unsigned char ret;
if(offset){
backup_offset=ftell(from.fp);
fseek(from.fp, offset, SEEK_SET);
}
ret=fgetc(from.fp);
if(offset) fseek(from.fp, backup_offset, SEEK_SET);
return(ret);
}
unsigned short read_SHORT(unsigned long offset)
{
unsigned long backup_offset;
unsigned short ret,ret2;
if(offset){
backup_offset=ftell(from.fp);
fseek(from.fp, offset, SEEK_SET);
}
ret =fgetc(from.fp);
ret2=fgetc(from.fp);
if(from.Intel) ret |= (ret2<<8);
else ret = (ret<<8) | ret2;
if(offset) fseek(from.fp, backup_offset, SEEK_SET);
return(ret);
}
unsigned long read_LONG(unsigned long offset)
{
unsigned long backup_offset;
unsigned long ret,a[4];
if(offset){
backup_offset=ftell(from.fp);
fseek(from.fp, offset, SEEK_SET);
}
a[0]=fgetc(from.fp);
a[1]=fgetc(from.fp);
a[2]=fgetc(from.fp);
a[3]=fgetc(from.fp);
if(from.Intel) ret=( a[0] | (a[1]<<8) | (a[2]<<16) | (a[3]<<24) );
else ret=( a[3] | (a[2]<<8) | (a[1]<<16) | (a[0]<<24) );
if(offset) fseek(from.fp, backup_offset, SEEK_SET);
return(ret);
}
/*
大きい型から小さい型へキャストする時は、下位バイトを取ると仮定している
IFDのVALUE読み込みのみに使うこと
*/
unsigned long read_VALUE( unsigned short type, unsigned long offset )
{
unsigned long ret;
switch( type ){
case BYTE_TYPE: case ASCII_TYPE:
ret = read_BYTE( offset );
fgetc(from.fp);fgetc(from.fp);fgetc(from.fp);
return( ret );
case SHORT_TYPE:
ret = read_SHORT( offset );
fgetc(from.fp);fgetc(from.fp);
return( ret );
case LONG_TYPE:
return( read_LONG( offset ) );
default:
puts("unexpected Rational type!");
exit(1);
}
}
/*
Intelフォーマットかどうかを調べる関数。
Mainに入れると変更がややこしくなりそうなので・・・
*/
int isIntel(void)
{
unsigned char first,second;
fseek(from.fp, (unsigned long)0, SEEK_SET);
first=fgetc(from.fp); second=fgetc(from.fp);
from.Intel=-1;
if( (first=='I') && (second=='I') ) from.Intel=1;
if( (first=='M') && (second=='M') ) from.Intel=0;
if( read_SHORT(0UL) == 0x2a ) return(1);
return(-1); /* not TIFF file */
}
/*
IFD(Image File Directry) を読み込む。
fpは予め、しかるべきところにセットされてること。
*/
#include"color.h"
void read_IFD(void)
{
unsigned int i,j,entry_num;
unsigned long offset,len, k;
unsigned short tag,type;
unsigned short *p;
unsigned long *pl;
/* from の初期化 */
from.Image_Width =
from.Image_Length =
from.Bits_Per_Sample =
from.Compression =
from.Photo_Interp =
from.Fill_Order =
from.Samples_Per_Pixel =
from.Max_Sample_Value =
from.Planer_Config = 0;
from.New_Subfile_Type =
from.X_Resolution.bunbo = from.X_Resolution.bunsi =
from.Y_Resolution.bunbo = from.Y_Resolution.bunsi =
from.Rows_Per_Strip = 0UL;
from.Strip_Offset =from.Strips_ByteCount = NULL;
from.RED = from.GREEN = from.BLUE = NULL;
from.Opacity = from.Color_Map = from.Strips = 0;
/* タグを読みます */
LOOP:
entry_num = read_SHORT(0UL);
for(i = 0; i<entry_num; i++){
tag = read_SHORT(0UL);
type= read_SHORT(0UL);
len = read_LONG(0UL);
switch(tag){
case 0xfe :
if( len!=1 ) goto UNREADABLE;
from.New_Subfile_Type = read_VALUE( type,0UL );
break;
case 0x100:
if( len!=1 ) goto UNREADABLE;
from.Image_Width = read_VALUE( type,0UL );
break;
case 0x101:
if( len!=1 ) goto UNREADABLE;
from.Image_Length = read_VALUE( type,0UL );
break;
case 0x102:
if( (type==SHORT_TYPE) && (len==1) ){
from.Bits_Per_Sample = read_SHORT(0UL);
fgetc(from.fp); fgetc(from.fp);
continue;
};
if( type==SHORT_TYPE ){
offset=ftell(from.fp); /* 現在位置のオフセットを保持 */
fseek( from.fp, read_LONG(0UL), SEEK_SET );
/* short*3でRGBのビット数を記録してある場合 */
from.Bits_Per_Sample = 0;
for( j=0; j<len; j++ ) from.Bits_Per_Sample += read_SHORT(0UL);
if( len == 4 ) from.Opacity = 1; else from.Opacity = 0; /* 透明度付き */
fseek(from.fp, offset+4, SEEK_SET); /* fpをもとに戻す */
continue;
};
goto UNREADABLE;
case 0x103:
if( len!=1 ) goto UNREADABLE;
from.Compression = read_VALUE( type,0UL);
break;
case 0x106:
if( len!=1 ) goto UNREADABLE;
from.Photo_Interp = read_VALUE( type,0UL);
break;
case 0x10a:
if( len!=1 ) goto UNREADABLE;
from.Fill_Order = read_VALUE( type,0UL);
break;
case 0x111:
if(type!=LONG_TYPE) goto UNREADABLE;
from.Strip_Offset = pl = MALLOC((size_t)(len*4+4));
from.Strips=len;
if(len==1){
*pl=read_LONG(0UL);
*(pl+1)=0;
break;
};
offset=ftell(from.fp);
fseek(from.fp, read_LONG(0UL), SEEK_SET);
for(j=0; j<len; j++){
*pl=read_LONG(0UL);
pl++;
};
*pl=0; /* エンドマークの0 */
fseek(from.fp, offset+4, SEEK_SET);
break;
case 0x116:
if( len!=1 ) goto UNREADABLE;
from.Rows_Per_Strip = read_VALUE( type,0UL);
break;
case 0x115:
if( len!=1 ) goto UNREADABLE;
from.Samples_Per_Pixel= read_VALUE( type,0UL);
break;
case 0x117:
if(type!=LONG_TYPE) goto UNREADABLE;
from.Strips_ByteCount = pl = MALLOC(len*4+4);
from.Strips=len;
if(len==1){
*pl=read_LONG(0UL);
*(pl+1)=0;
break;
};
offset=ftell(from.fp);
fseek(from.fp, read_LONG(0UL), SEEK_SET);
for(j=0; j<len; j++){
*pl=read_LONG(0UL);
pl++;
};
*pl=0; /* エンドマークの0 */
fseek(from.fp, offset+4, SEEK_SET);
break;
case 0x119:
if( len!=1 ) goto UNREADABLE;
from.Max_Sample_Value = read_VALUE( type,0UL);
break;
case 0x11a:
if( (type!=RATIONAL_TYPE) || (len!=1) ) goto UNREADABLE;
offset=ftell(from.fp);
fseek(from.fp, read_LONG(0UL), SEEK_SET);
from.X_Resolution.bunsi = read_LONG(0UL);
from.X_Resolution.bunbo = read_LONG(0UL);
fseek(from.fp, offset+4, SEEK_SET);
break;
case 0x11b:
if( (type!=RATIONAL_TYPE) || (len!=1) ) goto UNREADABLE;
offset=ftell(from.fp);
fseek(from.fp, read_LONG(0UL), SEEK_SET);
from.Y_Resolution.bunsi = read_LONG(0UL);
from.Y_Resolution.bunbo = read_LONG(0UL);
fseek(from.fp, offset+4, SEEK_SET);
break;
case 0x11c:
if( len!=1 ) goto UNREADABLE;
from.Planer_Config = read_VALUE( type,0UL);
break;
case 0x140:
if( (type!=SHORT_TYPE) || (len%3) ) goto UNREADABLE;
from.Color_Map=1;
from.RED = MALLOC( (size_t)((len/3)*2) );
from.GREEN = MALLOC( (size_t)((len/3)*2) );
from.BLUE = MALLOC( (size_t)((len/3)*2) );
k=read_LONG(0UL);
offset=ftell(from.fp);
fseek(from.fp , k, SEEK_SET);
for(j=0, p=from.RED; j<len/3; j++){
*p= read_SHORT(0UL);
p++;
};
for(j=0, p=from.GREEN; j<len/3; j++){
*p= read_SHORT(0UL);
p++;
};
for(j=0, p=from.BLUE; j<len/3; j++){
*p= read_SHORT(0UL);
p++;
};
fseek(from.fp, offset, SEEK_SET);
break;
default :
UNREADABLE:
printf("解読できないタグです。tag:%04x type:%04x len:%08lx value:%08lX\n",tag,type,len,read_LONG(0UL) );
};
};
if( offset=read_LONG(0UL) ){
fseek(from.fp, offset, SEEK_SET);
goto LOOP;
};
/* パレットなしの8ビットデータに、パレットを付ける */
if( (from.Bits_Per_Sample==8) && (from.Color_Map==0) ){
from.RED = table_RED;
from.GREEN= table_GREEN;
from.BLUE = table_BLUE;
};
/* Rows_Per_Strip が省略されてるとき。 */
if( from.Rows_Per_Strip == 0 ){
from.Rows_Per_Strip = from.Image_Length;
from.Strips_ByteCount = MALLOC(4);
*from.Strips_ByteCount =
(UL_ from.Image_Width * UL_ from.Image_Length * UL_ from.Bits_Per_Sample) / 8UL;
/* Rows Per Strip の設定されてないLZWがあるのか? */
if( from.Compression == 5 )
puts("*注意* このTIFFを変換できるかは、不確定です。");
}
return;
}
/*
複数ブロック化されているデータも、単一ブロックに見せかけて出力。
エンドコードは256
*/
unsigned short read_Gdata(void)
{
static unsigned long strip_bytes=0; /* current strip で読んだバイト数 */
static unsigned int strip=0; /* current strip number */
static unsigned long offset, backup_offset;
static unsigned long stack_bytes=0; /* RAMに入ってるバイト数 */
static unsigned char *add,*pc;
static int INIT = 0;
unsigned short ret;
unsigned long bytes;
/* Initialize */
if( INIT==0 ){
offset=*from.Strip_Offset;
if( from.Compression == 5 ){
if( from.Bits_Per_Sample == 12 )
bytes = from.Image_Width * from.Rows_Per_Strip * 2;
else
bytes = from.Image_Width * from.Rows_Per_Strip * (from.Bits_Per_Sample/8UL);
pc=add=MALLOC( bytes );
}
else
pc=add=MALLOC((size_t)TEMP_SIZE);
stack_bytes = 0;
INIT = 1;
};
if( from.Compression == 5 ) goto LZW;
if(stack_bytes==0){ /* ディスクから読む必要がある */
backup_offset=ftell(from.fp); /* 現在のファイルポインタの保存 */
fseek(from.fp, offset, SEEK_SET);
bytes=TEMP_SIZE;
pc=add;
LOOP:
if( from.Strips<=strip ) goto XXX;
if( bytes>= *(from.Strips_ByteCount+strip)-strip_bytes ){
fread(pc, *(from.Strips_ByteCount+strip)-strip_bytes, 1, from.fp);
pc += *(from.Strips_ByteCount+strip)-strip_bytes;
stack_bytes += *(from.Strips_ByteCount+strip)-strip_bytes;
bytes -= *(from.Strips_ByteCount+strip)-strip_bytes;
strip++;
strip_bytes=0;
fseek(from.fp, *(from.Strip_Offset+strip), SEEK_SET);
goto LOOP;
}
else
if(bytes){
fread(pc, bytes, 1, from.fp);
strip_bytes+=bytes;
stack_bytes+=bytes;
}
XXX:
offset=ftell(from.fp);
fseek(from.fp, backup_offset, SEEK_SET);
printf("\rRead %lu bytes",stack_bytes);
pc=add;
if(stack_bytes==0){ /* それでもRAMにデータがない */
free(add);
return(256);
};
}
ret=*pc;
pc++;
stack_bytes--;
return(ret);
LZW: /* 圧縮ファイル */
if( stack_bytes == 0 ){
backup_offset = ftell(from.fp);
stack_bytes = uncompress(add);
fseek(from.fp, backup_offset, SEEK_SET);
printf(" %lu bytes\r",stack_bytes);
if( stack_bytes == 0 ) return(256);
pc = add;
}
ret = *pc;
pc++;
stack_bytes--;
return(ret);
}